pinia 基础
pinia overview
Pinia 是一个适用于 Vue2~3 的跨组件共享状态维持项目,与 vuex、bus 等原理类似,但都比前者简单高效许多,在 2019 年 11 年重新被设计使用,其维护团队为 Vuejs。
特点在于更加容易调试,可以使得 store
出现在其他组件中并使用,以及在不重新加载页面的情况下修改 store
共享数据,并保持现有状态,同时占用空间小的特点。
1 | 反观 Vuex 和专注于兄弟组件之间通信的 Bus 相比,Pinia 根据简单和[官方](https://github.com/vuejs/pinia)团队维护等特点深受开发人员喜爱。 |
Store
首先,Pinia 拥有和 Vuex 类似的特性及功能(毕竟是同类型项目),而 Store 的定义主要是可以让该数据被所有组件共享。
在本文中,我们主要通过 vue-cli 来构建 vue3 project,并使用 vue add vue-cli-plugin-pinia
来添加 pinia 支持。
之后可以在 src/store/
下看到其自动帮我们所创建的 pinia store,之后我们可以重命名或者直接在此基础上进行开发,来进行共享数据。
同时他也会在 mian.js
文件下为我们引入 pinia 并使用,返回给 Vue。
在使用的时候,你需要记得,在 store 目录下的共享数据内的方里,默认的会为:
1 | import { defineStore } from 'pinia' |
我们需要记得导出的方法,也就是 useCounterStore
之后在组件中直接 import { useCounterStore } from "@/stores/index"
这么引用,然后在 setup()
语法糖下赋值给 store
:
1 | setup() { |
这之后在 template
下,就可以通过插值 {{ store.count }}
来直接进行使用了。
1 | 这在官方文档关于定义 Store 中有详细的描述:“并且它需要一个唯一的名称,作为第一个参数传递” |
State
State 是 Stores
所定义的中心部分,也就是共享数据\状态的起点,在 PInia 中会被定义为返回初始的状态函数:
1 | import { defineStore } from 'pinia' |
Getters & Actions
Actions
在此之前,我们需要知道,getters
是被动获取,也就是说需要有组件取调用这个方法。而 Actions 则是可以实现在文章开头,Pinia 所说的特性之一:”Stores appear in components where they are used”,即可以在组件中实现将组件的数据,传入到 State 中。
1 | 需要注意的是,在一般情况下,Vuex、和 Bus 很难去解决组件和组件之间的传值,需要通过 emit,props 等方法,先将兄弟组件的数据传给父组件,父组件再将数据传给兄弟组件,以此来实现传值。 |
在组件传值之前,我们首先需要在 store
下定义参数,准备接受组件所传来的数据,并之后传给 state()
下的共享状态变量 rowItems
:
1 | import { defineStore } from 'pinia' |
1 | 在真实的开发环境中,一般先定义 ```state``` 下的共享变量,再去定义 ```actions```,之后才是 ```getters``` |
上述 Code 中,我们主要通过 this.rowItems.push
方法,来将获取到的 name
参数传递给 state
,之后 getters
来获取 state
下的共享数据/状态变量。
下面,我们需要通过在传递数据的组件内,引入 import { useTabStore } from "@/stores";
,之后按照 setup()
语法糖:
1 | export default defineComponent({ |
由于我们是按照 setup()
语法糖的 Vue3 的写法,那么基本上数据是在 setup()
下的 return
来进行编写,我们需要做的就是通过 tab.addItem(value)
将数据传递给 stores
,之后就完成了组件的传递。
Getters
1 |
|
在上述的 Code 中,我们首先在 state
先定义共享状态 rowItems
变量,当获取数据的时候,我们需要他可以循环遍历,那么就通过 reduce之后 方法来按照数组的顺序来进行返回。
然后通过 push 方法将元素添加至数组的末尾,最后返回 items
变量,这是通过 actions
所获取到的数据并输出。
在数据的获取部分,我们需要在组件中同样引入 import { useTabStore } from "@/stores/index"
,然后按照 setup()
语法糖的写法:
1 | export default defineComponent({ |
之后通过 template
的模板语法以及 v-for
和 v-bind
就可以完成共享数据的循环输出:
1 | <li v-for="item in store.items" :key="item.name"> |